#!/usr/bin/env python3
"""
Improved Markdown to LaTeX converter for Claude Code Development Book
Fixes issues with code blocks, special characters, and formatting
"""

import re
import os
from pathlib import Path

def escape_latex_text(text):
    """Escape LaTeX special characters properly"""
    # Don't escape if it's already a LaTeX command
    if text.strip().startswith('\\'):
        return text
    
    # Dictionary of LaTeX special characters and their escapes
    replacements = [
        ('\\', r'\textbackslash{}'),
        ('{', r'\{'),
        ('}', r'\}'),
        ('$', r'\$'),
        ('&', r'\&'),
        ('%', r'\%'),
        ('#', r'\#'),
        ('^', r'\textasciicircum{}'),
        ('_', r'\_'),
        ('~', r'\textasciitilde{}'),
    ]
    
    for char, escape in replacements:
        text = text.replace(char, escape)
    return text

def convert_headers(text):
    """Convert markdown headers to LaTeX sections"""
    lines = text.split('\n')
    result = []
    
    for line in lines:
        if line.startswith('#'):
            # Count the # symbols to determine level
            level = 0
            for char in line:
                if char == '#':
                    level += 1
                else:
                    break
            
            title = line[level:].strip()
            
            if level == 1:
                result.append(f'\\chapter{{{title}}}')
            elif level == 2:
                result.append(f'\\section{{{title}}}')
            elif level == 3:
                result.append(f'\\subsection{{{title}}}')
            elif level == 4:
                result.append(f'\\subsubsection{{{title}}}')
            elif level >= 5:
                result.append(f'\\paragraph{{{title}}}')
        else:
            result.append(line)
    
    return '\n'.join(result)

def convert_emphasis(text):
    """Convert markdown emphasis to LaTeX"""
    # Bold: **text** or __text__
    text = re.sub(r'\*\*(.*?)\*\*', r'\\textbf{\1}', text)
    text = re.sub(r'__(.*?)__', r'\\textbf{\1}', text)
    
    # Italic: *text* or _text_ (but avoid matching within words)
    text = re.sub(r'(?<!\w)\*([^\*\n]+?)\*(?!\w)', r'\\textit{\1}', text)
    text = re.sub(r'(?<!\w)_([^_\n]+?)_(?!\w)', r'\\textit{\1}', text)
    
    return text

def convert_code_blocks(text):
    """Convert markdown code blocks to LaTeX listings"""
    # Handle fenced code blocks with language specification
    pattern = r'^```(\w*)\n(.*?)^```'
    
    def replace_code_block(match):
        language = match.group(1) if match.group(1) else ''
        code_content = match.group(2)
        
        # Remove any existing escaping in code content
        # Code should not be escaped
        code_content = code_content.strip()
        
        # Map languages to listings-supported ones
        lang_map = {
            'bash': 'bash',
            'shell': 'bash',
            'sh': 'bash',
            'python': 'Python',
            'py': 'Python',
            'javascript': 'Java',
            'js': 'Java',
            'json': 'bash',
            'yaml': 'bash',
            'yml': 'bash',
            'markdown': 'bash',
            'md': 'bash',
            'latex': 'TeX',
            'tex': 'TeX',
            'sql': 'SQL',
            'html': 'HTML',
            'css': 'HTML',
            'xml': 'XML',
            'dockerfile': 'bash',
            'makefile': 'make',
            'c': 'C',
            'cpp': 'C++',
            'java': 'Java'
        }
        
        mapped_lang = lang_map.get(language.lower(), '')
        
        if mapped_lang:
            return f'\\begin{{lstlisting}}[language={mapped_lang}]\n{code_content}\n\\end{{lstlisting}}'
        else:
            return f'\\begin{{lstlisting}}\n{code_content}\n\\end{{lstlisting}}'
    
    # Apply the replacement
    text = re.sub(pattern, replace_code_block, text, flags=re.MULTILINE | re.DOTALL)
    
    # Handle inline code `code`
    def replace_inline_code(match):
        code = match.group(1)
        # Don't escape content in inline code
        return f'\\texttt{{{code}}}'
    
    text = re.sub(r'`([^`\n]+)`', replace_inline_code, text)
    
    return text

def convert_lists(text):
    """Convert markdown lists to LaTeX"""
    lines = text.split('\n')
    result = []
    in_list = False
    list_type = None
    
    for line in lines:
        stripped = line.strip()
        
        # Check for unordered list items
        if re.match(r'^[\s]*[-*+]\s+', line):
            if not in_list or list_type != 'itemize':
                if in_list and list_type:
                    result.append(f'\\end{{{list_type}}}')
                result.append('\\begin{itemize}')
                in_list = True
                list_type = 'itemize'
            
            # Extract content after the list marker
            content = re.sub(r'^[\s]*[-*+]\s+', '', line)
            result.append(f'\\item {content}')
            
        # Check for ordered list items  
        elif re.match(r'^[\s]*\d+\.\s+', line):
            if not in_list or list_type != 'enumerate':
                if in_list and list_type:
                    result.append(f'\\end{{{list_type}}}')
                result.append('\\begin{enumerate}')
                in_list = True
                list_type = 'enumerate'
            
            # Extract content after the number
            content = re.sub(r'^[\s]*\d+\.\s+', '', line)
            result.append(f'\\item {content}')
            
        else:
            # If we hit an empty line or non-list line, end the current list
            if in_list and (not stripped or not line.startswith(' ')):
                if list_type:
                    result.append(f'\\end{{{list_type}}}')
                in_list = False
                list_type = None
            
            result.append(line)
    
    # Close any remaining list
    if in_list and list_type:
        result.append(f'\\end{{{list_type}}}')
    
    return '\n'.join(result)

def convert_links(text):
    """Convert markdown links to LaTeX"""
    # [text](url) format
    text = re.sub(r'\[([^\]]+)\]\(([^)]+)\)', r'\\href{\2}{\1}', text)
    return text

def convert_tables(text):
    """Convert markdown tables to LaTeX tables"""
    lines = text.split('\n')
    result = []
    i = 0
    
    while i < len(lines):
        line = lines[i]
        
        # Check if this might be a table row
        if '|' in line and line.strip().startswith('|') and line.strip().endswith('|'):
            # Look for the separator line
            if i + 1 < len(lines) and re.match(r'^\s*\|[\s\-:|]+\|\s*$', lines[i + 1]):
                # We found a table
                header_cells = [cell.strip() for cell in line.split('|')[1:-1]]  # Remove empty first/last
                num_cols = len(header_cells)
                
                result.append('\\begin{table}[H]')
                result.append('\\centering')
                result.append(f'\\begin{{tabular}}{{|{"l|" * num_cols}}}')
                result.append('\\hline')
                result.append(' & '.join(header_cells) + ' \\\\')
                result.append('\\hline')
                
                # Skip the separator line
                i += 2
                
                # Process table rows
                while i < len(lines) and '|' in lines[i] and lines[i].strip():
                    row_line = lines[i]
                    if row_line.strip().startswith('|') and row_line.strip().endswith('|'):
                        row_cells = [cell.strip() for cell in row_line.split('|')[1:-1]]
                        if len(row_cells) == num_cols:
                            result.append(' & '.join(row_cells) + ' \\\\')
                    i += 1
                
                result.append('\\hline')
                result.append('\\end{tabular}')
                result.append('\\end{table}')
                continue
        
        result.append(line)
        i += 1
    
    return '\n'.join(result)

def process_content(content):
    """Process markdown content and convert to LaTeX"""
    
    # Step 1: Convert code blocks first (before any escaping)
    content = convert_code_blocks(content)
    
    # Step 2: Convert tables
    content = convert_tables(content)
    
    # Step 3: Convert headers
    content = convert_headers(content)
    
    # Step 4: Convert emphasis
    content = convert_emphasis(content)
    
    # Step 5: Convert lists
    content = convert_lists(content)
    
    # Step 6: Convert links
    content = convert_links(content)
    
    # Step 7: Escape special characters (but protect LaTeX commands and code blocks)
    lines = content.split('\n')
    processed_lines = []
    in_code_block = False
    
    for line in lines:
        # Check if we're in a code block
        if line.strip().startswith('\\begin{lstlisting}'):
            in_code_block = True
            processed_lines.append(line)
        elif line.strip().startswith('\\end{lstlisting}'):
            in_code_block = False
            processed_lines.append(line)
        elif in_code_block:
            # Don't escape anything in code blocks
            processed_lines.append(line)
        elif line.strip().startswith('\\'):
            # Don't escape LaTeX commands
            processed_lines.append(line)
        else:
            # Escape special characters in regular text
            processed_lines.append(escape_latex_text(line))
    
    return '\n'.join(processed_lines)

def convert_file(input_file, output_file):
    """Convert a single markdown file to LaTeX"""
    print(f"Converting {input_file} -> {output_file}")
    
    try:
        with open(input_file, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # Process the content
        latex_content = process_content(content)
        
        # Write the result
        with open(output_file, 'w', encoding='utf-8') as f:
            f.write(latex_content)
            
        print(f"Successfully converted {input_file}")
        
    except Exception as e:
        print(f"Error converting {input_file}: {e}")

def main():
    """Convert all markdown files"""
    book_dir = Path("/home/linden/claude/packages/ccwork/claude-code-development-book")
    chapters_dir = book_dir / "chapters"
    
    # Create output directory
    chapters_dir.mkdir(exist_ok=True)
    
    # Find all markdown files
    md_files = []
    
    # Foundation files
    foundation_dir = book_dir / "part-i-foundation"
    if foundation_dir.exists():
        md_files.extend(sorted(foundation_dir.glob("*.md")))
    
    # Task types files  
    task_types_dir = book_dir / "part-ii-task-types"
    if task_types_dir.exists():
        md_files.extend(sorted(task_types_dir.glob("*.md")))
    
    # Advanced files
    advanced_dir = book_dir / "part-iii-advanced"
    if advanced_dir.exists():
        md_files.extend(sorted(advanced_dir.glob("*.md")))
    
    # Appendices files
    appendices_dir = book_dir / "appendices"
    if appendices_dir.exists():
        md_files.extend(sorted(appendices_dir.glob("*.md")))
    
    print(f"Found {len(md_files)} files to convert")
    
    # Convert each file
    for md_file in md_files:
        # Generate output filename
        basename = Path(md_file).stem
        output_filename = f"{basename}.tex"
        output_path = chapters_dir / output_filename
        
        convert_file(md_file, output_path)
    
    print("Conversion complete!")

if __name__ == "__main__":
    main()